package com.jesse.custom.asyncimageview;

import com.jesse.main.R;
import com.jesse.util.ViewUtil;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * 带有内存缓存，和SD卡缓存与缩放功能的异步加载图片资源的ImageView，适合显示网络图片，自带资源图片。
 * 
 * 其内存缓存方式为LruCache，其中核心类为{@link AsyncImageLoader},该类提供了缓存操作。
 * 
 * 而图片的缩放由缩放类{@link AsyncImageScale}提供
 * 
 * @author jesse
 */
public class AsyncImageView extends ImageView{

	private Context context;
	/**
	 * 图片读取核心方法
	 */
	private AsyncImageLoader asyncImageLoader;
	
	/**
	 * 图片读取进度回调
	 */
	private AsyncImageviewSetviewComplete asyncImageviewSetviewCompleteDao;
	
	/**
	 * 图片下载地址
	 */
	private String url;
	
	/**
	 * Imageview所加载图片的宽度
	 */
	private int imageviewWidthwidh;
	
	/**
	 * Imageview所加载图片的高度
	 */
	private int imageviewHeight;
	
	/**
	 * 自定义传递信息
	 */
	private Object tag;
	
	public Object getTag() {
		return tag;
	}

	public void setTag(Object tag) {
		this.tag = tag;
	}

	/**
	 * 等待，加载中默认显示图片
	 */
	private int loadingImageResId;
	
	public void setLoadingImage(int rId) {
		this.loadingImageResId = rId;
	}

	public AsyncImageView(Context context) {
		super(context);
		this.context = context;
		asyncImageLoader = AsyncImageLoader.getInstance();
	}
	
	public AsyncImageView(Context context, AttributeSet attr) {
		super(context, attr);
		this.context = context;
		asyncImageLoader = AsyncImageLoader.getInstance();
	}

	
	/**
	 * 设置读取进度回调{@link AsyncImageviewSetviewComplete}
	 * 1.onError
	 * 2.onLoading
	 * 3.onComplete
	 * @param asyncImageviewSetviewCompleteDao
	 */
	public void setAsyncImageviewSetviewCompleteDao(
			AsyncImageviewSetviewComplete asyncImageviewSetviewCompleteDao) {
		this.asyncImageviewSetviewCompleteDao = asyncImageviewSetviewCompleteDao;
	}

	/**
	 * 根据图片地址下载图片
	 * @param url	图片地址
	 * @param iconKey	该图片的索引key（推荐使用地址+图片宽高组成的MD5值）
	 * @return 返回下载好的图片资源，当下载完成会自动setImage，该返回值是用于其他操作。
	 */
	public Drawable getIconWithUrl(String url, String iconKey) {
		return getIconWithUrlScale(url, iconKey, 0, 0);
	}
	
	/**
	 * 根据图片地址下载图片,并且以宽度值为等比缩放
	 * @param url	图片地址
	 * @param iconKey	该图片的索引key（推荐使用地址+图片宽高组成的MD5值）
	 * @param width		想指定的图片宽度
	 * @return	返回下载并缩放过的图片资源，当下载完成会自动setImage，该返回值是用于其他操作。
	 */
	public Drawable getIconWithUrlScaleByWidth(String url, String iconKey, int width) {
		Drawable drawable = getIconWithUrlScale(url, iconKey, width, 0);
		return drawable;
	}
	
	/**
	 * 根据图片地址下载图片,并且以高度值为等比缩放
	 * @param url	图片地址
	 * @param iconKey	该图片的索引key（推荐使用地址+图片宽高组成的MD5值）
	 * @param hight		想指定的图片高度
	 * @return		返回下载并缩放过的图片资源，当下载完成会自动setImage，该返回值是用于其他操作。
	 */
	public Drawable getIconWithUrlScaleByHight(String url, String iconKey, int hight) {
		Drawable drawable = getIconWithUrlScale(url, iconKey, 0, hight);
		return drawable;
	}
	
	/**
	 * 根据图片地址下载图片,并且指定宽高缩放，非等比缩放
	 * @param url	图片地址
	 * @param iconKey	该图片的索引key（推荐使用地址+图片宽高组成的MD5值）
	 * @param width		想指定的图片宽度
	 * @param hight		想指定的图片高度
	 * @return		返回下载并缩放过的图片资源，当下载完成会自动setImage，该返回值是用于其他操作。	
	 */
	public Drawable getIconWithUrlScale(String url, String iconKey, int width, int hight) {
		Drawable drawable = getDrawable(url, iconKey, width, hight);
		return drawable;
	}
	
	/**
	 * 下载图片，设置图片核心方法。
	 * 
	 * 1.当下载地址为空时，自动显示图片为下载失败图片
	 * 
	 * 2.当下载中时，自动显示图片为Loading
	 * 
	 * 3.下载完成后，自动显示为缩放后，或未经缩放的图片。
	 * 
	 * @param url
	 * @param iconKey
	 * @param width
	 * @param hight
	 * @return	返回最终结果，或下载中的loading图片。
	 */
	private Drawable getDrawable (String url, final String iconKey, final int width, final int hight) {
		if (url.isEmpty()) {
			if (asyncImageviewSetviewCompleteDao != null) {
				asyncImageviewSetviewCompleteDao.onError(this.getDrawable(), tag);
			}
			return this.getDrawable();
		}
		
		/**
		 * 图片下载
		 */
		asyncImageLoader.loadDrawable(url, iconKey, width, hight, new AsynImageDownloadDao() {
			
			@Override
			public void imageLoaded(Bitmap imageBitmap, String imageUrl, Object msg) {
				if (imageBitmap == null && (Integer)msg == -1) {
//					setImage(transforLoadingIconKey(iconKey), loadingImageResId, width, hight); 
					if (asyncImageviewSetviewCompleteDao != null) {
						asyncImageviewSetviewCompleteDao.onPrepare(AsyncImageView.this.getDrawable(), tag);
					}
				}
				if (imageBitmap == null && (Integer)msg >= 0) {
					if (asyncImageviewSetviewCompleteDao != null) {
						asyncImageviewSetviewCompleteDao.onLoading(AsyncImageView.this.getDrawable(), (Integer)msg, tag);
					}
				} 
				if (imageBitmap != null) {
					setImage(iconKey, imageBitmap, width, hight); 
					setImageviewWidth(imageBitmap.getWidth());
					setImageviewHeight(imageBitmap.getHeight());
					if (asyncImageviewSetviewCompleteDao != null) {
						asyncImageviewSetviewCompleteDao.onComplete(imageBitmap, imageBitmap.getWidth(), imageBitmap.getHeight(), tag);
					}
				}
			}
		});
		return this.getDrawable();
	}

	private void setImage(String iconKey, int id, int width, int hight) {
		setImage(iconKey, context.getResources().getDrawable(id), width, hight);
	}
	
	private void setImage(String iconKey, Drawable drawable, int width, int hight) {
		setImage(iconKey, ((BitmapDrawable)drawable).getBitmap(), width, hight);
	}
	
	/**
	 * 用于图片缩放的方法，其中{@link AsyncImageScale} 是核心类。
	 * @param iconKey
	 * @param bmp
	 * @param width
	 * @param hight
	 */
	private void setImage(String iconKey, Bitmap bmp, int width, int hight) {
		AsyncImageScale imageScale = new AsyncImageScale(iconKey, bmp, width, hight);
		//TODO 暂停使用sclae功能，会导致内存溢出，返回值为原Bitmap
		Bitmap newBitmap = imageScale.scaleToBitmap();
		setImageBitmap(newBitmap);
	}
	
	/**
	 * 对于Loading图片，也将其放入到缓存中，其默认key值有变
	 * @param iconKey
	 * @return
	 */
	private String transforLoadingIconKey(String iconKey) {
		return iconKey+"loading";
	}
	
	/**
	 * 下载失败的图片，也放入缓存，其默认key值有变
	 * @param iconKey
	 * @return
	 */
	private String transforErrorIconKey(String iconKey) {
		return iconKey+"error";
	}
	
	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}
	
	public int getImageviewWidthwidh() {
		return imageviewWidthwidh;
	}

	private void setImageviewWidth(int imageviewWidthwidh) {
		this.imageviewWidthwidh = imageviewWidthwidh;
	}

	public int getImageviewHeight() {
		return imageviewHeight;
	}

	private void setImageviewHeight(int imageviewHeight) {
		this.imageviewHeight = imageviewHeight;
	}

	@Override  
    protected void onDraw(Canvas canvas) {  
        try {  
            super.onDraw(canvas);  
        } catch (Exception e) {  
            ViewUtil.Debug("MyImageView  -> onDraw() Canvas: trying to use a recycled bitmap");  
        }  
    }  
	
	public static void recycleImageView(ImageView view) {
		if (view.getDrawable() != null && view.getDrawable() instanceof BitmapDrawable){
			Bitmap oldBitmap = ((BitmapDrawable)view.getDrawable()).getBitmap();
			if (oldBitmap != null && !oldBitmap.isRecycled()) {
				oldBitmap.recycle();
				oldBitmap = null;
			}
		}
	}
}
